from urllib.parse import urlparse, parse_qs
import os
from datetime import datetime, timedelta
import traceback
import psutil
import gc

# 在文件顶部添加导入
from utils.config_manager import config

# 修改 FileLogger 类的初始化方法
class FileLogger:
    def __init__(self, log_file=None, max_size_mb=10, backup_count=3):
        """
        初始化文件日志记录器

        Args:
            log_file: 日志文件路径，如果为None则使用配置管理器中的路径
            max_size_mb: 单个日志文件最大大小（MB）
            backup_count: 保留的备份文件数量
        """
        self.log_file = log_file if log_file else config.get_log_file()
        self.max_size = max_size_mb * 1024 * 1024  # 转换为字节
        self.backup_count = backup_count

        # 确保日志目录存在
        log_dir = os.path.dirname(os.path.abspath(self.log_file))
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)

        # 创建或追加到日志文件
        with open(self.log_file, 'a', encoding='utf-8') as f:
            f.write(f"\n{'=' * 80}\n")
            f.write(f"=== 日志开始于 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ===\n")
            f.write(f"{'=' * 80}\n\n")

    def _check_log_size(self):
        """检查日志文件大小，如果超过限制则进行轮转"""
        try:
            if os.path.exists(self.log_file) and os.path.getsize(self.log_file) > self.max_size:
                self._rotate_logs()
        except Exception as e:
            print(f"检查日志大小时出错: {e}")

    def _rotate_logs(self):
        """执行日志文件轮转"""
        try:
            # 删除最旧的备份（如果存在）
            oldest_backup = f"{self.log_file}.{self.backup_count}"
            if os.path.exists(oldest_backup):
                os.remove(oldest_backup)

            # 轮转现有备份
            for i in range(self.backup_count - 1, 0, -1):
                src = f"{self.log_file}.{i}"
                dst = f"{self.log_file}.{i + 1}"
                if os.path.exists(src):
                    os.rename(src, dst)

            # 重命名当前日志文件为第一个备份
            if os.path.exists(self.log_file):
                os.rename(self.log_file, f"{self.log_file}.1")

            # 创建新的日志文件
            with open(self.log_file, 'w', encoding='utf-8') as f:
                f.write(f"=== 日志轮转于 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ===\n\n")
        except Exception as e:
            print(f"轮转日志文件时出错: {e}")

    def _format_message(self, level, message):
        """格式化日志消息"""
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
        # 获取调用者信息
        caller_frame = traceback.extract_stack()[-3]  # -3 跳过当前函数和log函数
        file_name = os.path.basename(caller_frame.filename)
        line_num = caller_frame.lineno

        return f"[{timestamp}] [{level}] [{file_name}:{line_num}] {message}"

    def log(self, message, level="INFO"):
        """
        记录日志到文件

        Args:
            message: 日志消息
            level: 日志级别（INFO, WARNING, ERROR, DEBUG, CRITICAL）
        """
        self._check_log_size()
        log_entry = self._format_message(level, message) + "\n"
        print(log_entry)
        try:
            with open(self.log_file, 'a', encoding='utf-8') as f:
                f.write(log_entry)
        except Exception as e:
            print(f"写入日志失败: {e}")

    def info(self, message):
        """记录INFO级别日志"""
        self.log(message, "INFO")

    def warning(self, message):
        """记录WARNING级别日志"""
        self.log(message, "WARNING")

    def error(self, message, exc_info=None):
        """
        记录ERROR级别日志，可选择包含异常堆栈

        Args:
            message: 错误消息
            exc_info: 是否包含异常堆栈信息
        """
        if exc_info:
            error_details = traceback.format_exc()
            self.log(f"{message}\n{error_details}", "ERROR")
        else:
            self.log(message, "ERROR")

    def debug(self, message):
        """记录DEBUG级别日志"""
        self.log(message, "DEBUG")

    def critical(self, message):
        """记录CRITICAL级别日志"""
        self.log(message, "CRITICAL")

    def section(self, title):
        """
        添加一个分隔区块到日志中

        Args:
            title: 区块标题
        """
        separator = "=" * 40
        self.log(f"\n{separator}\n{title}\n{separator}", "INFO")

    def step(self, step_name):
        """
        记录操作步骤

        Args:
            step_name: 步骤名称
        """
        self.log(f"执行步骤: {step_name}", "INFO")

    def result(self, operation, success, details=None):
        """
        记录操作结果

        Args:
            operation: 操作名称
            success: 是否成功
            details: 详细信息（可选）
        """
        status = "成功" if success else "失败"
        message = f"操作 '{operation}' {status}"
        if details:
            message += f": {details}"

        level = "INFO" if success else "WARNING"
        self.log(message, level)


file_logger = FileLogger()




def get_session_id(page):
    """从 URL 中提取 sessionId"""
    url = page.url
    parsed_url = urlparse(url)
    query_params = parse_qs(parsed_url.query)
    session_id = query_params.get("sessionId", [None])[0]
    return session_id


def check_jj(data_list, has_text="对方拒绝与您交换微信"):
    if not data_list:
        return False
    for item in data_list:
        if item.get("text","") and item.get("text","").__contains__(has_text):
            return True
    return False


def safe_inner_text(element, default=""):
    """Safely extract inner text from an element, return default if element is None or empty."""
    try:
        return element.inner_text().strip() if element else default
    except Exception:
        return default


def safe_get_attribute(element, attribute, default=""):
    """Safely get an attribute from an element, return default if element is None or attribute is missing."""
    try:
        return element.get_attribute(attribute) if element else default
    except Exception:
        return default


def scroll_view_and_click(item, page):
    if not item.is_visible():
        item.scroll_into_view_if_needed()
        page.wait_for_timeout(1000)

    item.click()
    page.wait_for_timeout(1000)

def check_hd_page(page):
    # 进来了再检测下页面对不对。
    # 1. 检查URL是否正确
    current_url = page.url
    if not current_url.startswith("https://rd6.zhaopin.com/app/im"):
        file_logger.log(f"页面URL不正确，当前URL: {current_url}")
        page.wait_for_timeout(2000)
        return False

    # 2. 检查页面特征元素，确认是聊天页面
    try:
        # 检查智联招聘聊天页面的特征元素
        page_features = [
            "//main[@class='im-page__inner km-main']",  # 主聊天容器
            "//section[@class='im-container km-layout']",  # 聊天布局容器
            "//aside[@class='km-aside im-aside im-aside--left im-aside--page']",  # 左侧聊天列表
        ]

        # 检查所有特征元素是否存在
        for feature in page_features:
            if not page.query_selector(feature):
                file_logger.log(f"页面特征元素缺失: {feature}")
                return False

        file_logger.log("页面验证通过")

    except Exception as e:
        file_logger.error(f"页面验证时出错: {e}")
        return False

    return True



def check_gt_page(page):
    # 进来了再检测下页面对不对。
    # 1. 检查URL是否正确
    current_url = page.url
    if not current_url.startswith("https://rd6.zhaopin.com/app/recommend"):
        file_logger.log(f"页面URL不正确，当前URL: {current_url}")
        page.wait_for_timeout(2000)
        return False

     # 2. 检查页面特征元素，确认是人才推荐页面
    try:
        # 检查智联招聘人才推荐页面的特征元素
        page_features = [
            "//div[@class='page-view__content']",  # 页面主内容容器
            "//div[@class='talent-job__job-wrap']",  # 职位包装容器
            "//div[@class='recommend-list']",  # 推荐列表容器
        ]

        # 检查所有特征元素是否存在
        for feature in page_features:
            if not page.query_selector(feature):
                file_logger.log(f"页面特征元素缺失: {feature}")
                return False

        file_logger.log("页面验证通过")

    except Exception as e:
        file_logger.error(f"页面验证时出错: {e}")
        return False

    return True



class ResourceMonitor:
    """资源监控和管理类"""
    def __init__(self, memory_threshold=95, cpu_threshold=90):
        self.memory_threshold = memory_threshold  # 内存使用率阈值(%)
        self.cpu_threshold = cpu_threshold        # CPU使用率阈值(%)
        self.last_cleanup = datetime.now()
        self.cleanup_interval = timedelta(minutes=10)  # 清理间隔

    def check_memory_usage(self):
        """检查内存使用情况"""
        memory = psutil.virtual_memory()
        return memory.percent

    def check_cpu_usage(self):
        """检查CPU使用情况"""
        return psutil.cpu_percent(interval=1)

    def should_cleanup(self):
        """判断是否需要清理"""
        now = datetime.now()
        memory_usage = self.check_memory_usage()

        # 内存超过阈值或到达清理间隔
        return (memory_usage > self.memory_threshold or
                now - self.last_cleanup > self.cleanup_interval)

    def force_cleanup(self):
        return
        """强制清理内存"""
        file_logger.log(f"执行内存清理，当前内存使用率: {self.check_memory_usage()}%")
        gc.collect()  # 强制垃圾回收
        self.last_cleanup = datetime.now()
        file_logger.log(f"内存清理完成，清理后内存使用率: {self.check_memory_usage()}%")





def check_resume_completeness(datajson_str):
    import json

    """
    检查简历数据是否完整（除了name、age、wechat之外是否还有其他有效字段）
    :param datajson_str: JSON字符串格式的简历数据
    :return: True表示有其他有效字段，False表示只有基本信息
    """
    try:
        data = json.loads(datajson_str)
        personal_info = data.get("personal_info", {})
        
        # 检查personal_info中除了name、age、wechat之外的字段是否有值
        other_personal_fields = [
            "work_experience", "education_level", "current_status", 
            "location", "phone", "gender"
        ]
        
        for field in other_personal_fields:
            if personal_info.get(field) and personal_info.get(field).strip():
                return True
        
        # 检查其他主要字段是否有内容
        main_fields = [
            "job_expectations", "work_experiences", "project_experiences", 
            "education", "training_experiences", "personal_works"
        ]
        
        for field in main_fields:
            field_data = data.get(field, [])
            if field_data and len(field_data) > 0:
                return True
        
        # 检查personal_advantages是否有内容
        personal_advantages = data.get("personal_advantages", "")
        if personal_advantages and personal_advantages.strip():
            return True
            
        return False
        
    except (json.JSONDecodeError, Exception) as e:
        print(f"解析简历数据出错: {e}")
        return False